﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using FireStarter.CodeGeneration;
using FireStarterModeller.BO;
using NUnit.Framework;

namespace FireStarter.Test.CodeGeneration
{
    [TestFixture]
    public class TestUIWinProjectGenerator : TestProjectGeneratorBase
    {
        private static UIWinProjectGenerator CreateUIWinProjectReadyToGenerate()
        {
            UIWinProjectGenerator projectGenerator = new UIWinProjectGenerator();
            CreateSolutionGenerator(projectGenerator);
            projectGenerator.ProjectPath = GetRootedPath(Path.Combine(TEST_PROJECTS_FOLDER, GetRandomString()));
            projectGenerator.ProjectName = "TestProject.UI.Win";
            projectGenerator.SolutionGenerator.SolutionTypeName = GetRandomString();
            projectGenerator.ModelSolution.BOProjectName = GetRandomString();
            return projectGenerator;
        }

        protected override IProjectGenerator CreateProjectGenerator()
        {
            return new UIWinProjectGenerator();
        }

        protected override IProjectGenerator CreateProjectReadyToGenerate()
        {
            return CreateUIWinProjectReadyToGenerate();
        }

        [Test]
        public void TestGenerate_Fails_SolutionTypeNameNotSet()
        {
            //---------------Set up test pack-------------------
            IProjectGenerator projectGenerator = CreateProjectReadyToGenerate();
            projectGenerator.SolutionGenerator.SolutionTypeName = null;
            //---------------Assert Precondition----------------
            Assert.IsNull(projectGenerator.SolutionGenerator.SolutionTypeName);
            //---------------Execute Test ----------------------
            Exception exception = null;
            try
            {
                projectGenerator.Generate();
            }
            catch (Exception ex)
            {
                exception = ex;
            }
            //---------------Test Result -----------------------
            Assert.IsNotNull(exception, "Exception Expected");
            Assert.IsInstanceOf(typeof(PropertyMissingException), exception);
            PropertyMissingException propertyMissingException = (PropertyMissingException)exception;
            Assert.AreEqual("SolutionTypeName", propertyMissingException.PropertyName);
        }

        [Test]
        public void Test_GenerateControlFactory_DualWINVWG_ReturnsTrue()
        {
            //---------------Set up test pack-------------------
            UIWinProjectGeneratorSpy projectGenerator = new UIWinProjectGeneratorSpy();
            projectGenerator.SolutionGenerator = new SolutionGenerator();
            projectGenerator.SolutionGenerator.SolutionTypeName = GenerationTypes.SOLUTION_TYPE_DUALWINVWG;
            //---------------Assert Precondition----------------
            Assert.AreEqual(GenerationTypes.SOLUTION_TYPE_DUALWINVWG, projectGenerator.SolutionGenerator.SolutionTypeName);
            //---------------Execute Test ----------------------
            bool actualGenerateControlFactory = projectGenerator.CallGenerateControlFactory();
            //---------------Test Result -----------------------
            Assert.IsTrue(actualGenerateControlFactory);
        }

        [Test]
        public void Test_GenerateControlFactory_Other_ReturnsFalse()
        {
            //---------------Set up test pack-------------------
            UIWinProjectGeneratorSpy projectGenerator = new UIWinProjectGeneratorSpy();
            projectGenerator.SolutionGenerator = new SolutionGenerator();
            projectGenerator.SolutionGenerator.SolutionTypeName = GenerationTypes.SOLUTION_TYPE_VWG;
            //---------------Assert Precondition----------------
            Assert.AreEqual(GenerationTypes.SOLUTION_TYPE_VWG, projectGenerator.SolutionGenerator.SolutionTypeName);
            //---------------Execute Test ----------------------
            bool actualGenerateControlFactory = projectGenerator.CallGenerateControlFactory();
            //---------------Test Result -----------------------
            Assert.IsFalse(actualGenerateControlFactory);
        }

        [Test]
        public void TestGenerate_Creates_ProjectFile_IfDoesNotExist()
        {
            //---------------Set up test pack-------------------
            UIWinProjectGenerator uiWinProjectGenerator = CreateUIWinProjectReadyToGenerate();
            string projectFileName = uiWinProjectGenerator.ProjectFileName;
            //---------------Assert Precondition----------------
            Assert.IsFalse(File.Exists(projectFileName));
            //---------------Execute Test ----------------------
            uiWinProjectGenerator.Generate();
            //---------------Test Result -----------------------
            AssertProjectGeneratedCorrectly(uiWinProjectGenerator);
        }

        private static void AssertProjectGeneratedCorrectly(UIWinProjectGenerator uiWinProjectGenerator)
        {
            string libFolderName = uiWinProjectGenerator.SolutionGenerator.HabaneroReferencePath;
            libFolderName = Utilities.GetRelativePath(libFolderName, uiWinProjectGenerator.ProjectPath);
            string projectFileName = uiWinProjectGenerator.ProjectFileName;
            Assert.IsTrue(Directory.Exists(uiWinProjectGenerator.ProjectPath));
            Assert.IsTrue(File.Exists(projectFileName));
            ProjectFileManager projectFileManager = new ProjectFileManager(projectFileName, CodeTemplateEnum.CSharpVisualStudio2005);
            Assert.AreEqual(OutputType.Library, projectFileManager.OutputType);
            string projectFileContents = File.ReadAllText(projectFileName);
            StringAssert.Contains(@"<Compile Include=""Properties\AssemblyInfo.cs"" />", projectFileContents);
            AssertHasReference(projectFileContents, string.Format(@"{0}\Habanero.Base.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\Habanero.BO.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\Habanero.Faces.Base.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\Habanero.Faces.Win.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\log4net.dll", libFolderName));
            AssertHasSystemReference(projectFileContents, string.Format(@"System.Windows.Forms"));
        }

        [Test]
        public void TestGenerate_AddsControlFactory_IfDualWINVWG()
        {
            //---------------Set up test pack-------------------
            UIWinProjectGenerator projectGenerator = CreateUIWinProjectReadyToGenerate();
            projectGenerator.SolutionGenerator.SolutionTypeName = GenerationTypes.SOLUTION_TYPE_DUALWINVWG;
            //---------------Assert Precondition----------------
            Assert.AreEqual(GenerationTypes.SOLUTION_TYPE_DUALWINVWG, projectGenerator.SolutionGenerator.SolutionTypeName);
            //---------------Execute Test ----------------------
            projectGenerator.Generate();
            //---------------Test Result -----------------------
            string projectFileContents = File.ReadAllText(projectGenerator.ProjectFileName);
            string controlFactoryName = projectGenerator.SolutionGenerator.ModelSolution.ApplicationName + "ControlFactoryWin.cs";
            StringAssert.Contains(@"<Compile Include=""" + controlFactoryName + @""" />", projectFileContents);
        }

        [Test]
        public void TestGenerate_DoesNotAddIControlFactory_IfOther()
        {
            //---------------Set up test pack-------------------
            UIWinProjectGenerator projectGenerator = CreateUIWinProjectReadyToGenerate();
            projectGenerator.SolutionGenerator.SolutionTypeName = GenerationTypes.SOLUTION_TYPE_WIN;
            //---------------Assert Precondition----------------
            Assert.AreEqual(GenerationTypes.SOLUTION_TYPE_WIN, projectGenerator.SolutionGenerator.SolutionTypeName);
            //---------------Execute Test ----------------------
            projectGenerator.Generate();
            //---------------Test Result -----------------------
            string projectFileContents = File.ReadAllText(projectGenerator.ProjectFileName);
            string controlFactoryName = projectGenerator.SolutionGenerator.ModelSolution.ApplicationName + "ControlFactoryWin.cs";
            Assert.IsFalse(projectFileContents.Contains(@"<Compile Include=""" + controlFactoryName + @""" />"));
        }
    }

    class UIWinProjectGeneratorSpy : UIWinProjectGenerator
    {

        public bool CallGenerateControlFactory()
        {
            return base.GenerateControlFactory();
        }
    }
}
